﻿#include <iostream>
#include <conio.h>
#include <thread>
#include <windows.h>
#include <fstream>
using namespace std;

#define MAX 100
//dòng và cột của 2 ma trận
int MatrixAx, MatrixAy, MatrixBx, MatrixBy;

int Result[MAX][MAX];
int MatranA[MAX][MAX];
int MatrixB[MAX][MAX];

int MulMatrix();
void ProcessLineThread();
void ProcessLine(int line);
int** InputMatrix(int Matrixx, int Matrixy);
void PrintfMatrix(int Matrix[MAX][MAX], int Matrixx, int Matrixy);

void main()
{
	ifstream inFile;
	inFile.open("A.IN");
	if (!inFile)
		cout << "I cant do anything!" << endl;
	else
	{
		inFile>>MatrixAx >> MatrixAy ;
		for (int i = 0; i < MatrixAx; i++)
			{
			for (int j = 0; j < MatrixAy; j++)
				inFile >> MatranA[i][j];
			}
			inFile.close();	
	}

	inFile.open("B.IN");
	if (!inFile)
		cout << "I cant do anything!" << endl;
	else
	{
		inFile>>MatrixBx >> MatrixBy;
		for (int i = 0; i < MatrixBx; i++)
		{
			for (int j = 0; j < MatrixBy; j++)
				inFile >> MatrixB[i][j];
		}
		inFile.close();
	}

	PrintfMatrix(MatranA, MatrixAx, MatrixAy);
	cout << endl;
	PrintfMatrix(MatrixB, MatrixBx, MatrixBy);
	cout << endl;
	if (MulMatrix())
	{
		PrintfMatrix(Result, MatrixAx, MatrixBy);

		ofstream outFile;
		outFile.open("RS.OUT");
		if (!outFile)
			cout << "Cant do somthing else" << endl;
		else
		{
			outFile << MatrixAx << " " << MatrixBy << endl;
			for (int i = 0; i < 10; i++)
			{
				for (int j = 0; j < 10; j++)
					outFile << Result[i][j] << " ";
				outFile << endl;
			}
		}
	}
	else
		cout << "Ma tran khong hop le!";
	_getch();
}

void ProcessLine(int line)
{
	for (int i = 0; i < MatrixBy; i++) 
	{
		Result[line][i] = 0;
		for (int j = 0; j < MatrixAy; j++)
			Result[line][i] += MatranA[line][j] * MatrixB[j][i];
	}
}

int MulMatrix()
{
	// tối đa đc 4 luồng cho máy 2 nhân
	if (MatrixAy != MatrixBx)
		return 0;
	int group = 0;
	while (group < (MatrixAx / 4))
	{
		thread t1(ProcessLine, group * 4);
		thread t2(ProcessLine, group * 4 + 1);
		thread t3(ProcessLine, group * 4 + 2);
		thread t4(ProcessLine, group * 4 + 3);
		t1.join(); t2.join(); t3.join(); t4.join();
		group++;
	}
	auto remain = MatrixAx - group * 4;
	if (remain == 3){
		thread t1(ProcessLine, group * 4);
		thread t2(ProcessLine, group * 4 + 1);
		thread t3(ProcessLine, group * 4 + 2);
		t1.join(); t2.join(); t3.join();
		return 1;
	}
	else if (remain == 2){
		thread t1(ProcessLine, group * 4);
		thread t2(ProcessLine, group * 4 + 1);
		t1.join(); t2.join();
		return 1;
	}
	else if (remain == 1){
		thread t1(ProcessLine, group * 4);
		t1.join();
		return 1;
	}
	return 1;
}
int** InputMatrix(int Matrixx, int Matrixy)
{
	auto resultM = new int*[Matrixx];
	for (int i = 0; i < Matrixx; i++)
	{
		resultM[i] = new int[Matrixy];
		for (int j = 0; j < Matrixy; j++)
			cin >> resultM[i][j];
	}
	return resultM;
}

void PrintfMatrix(int Matrix[MAX][MAX], int Matrixx, int Matrixy)
{
	for (int i = 0; i < Matrixx; i++)
	{
		for (int j = 0; j < Matrixy; j++)
			cout << Matrix[i][j] << " ";
		cout << endl;
	}
}
